package com.legal.filter;

import com.legal.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import jakarta.servlet.FilterChain;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author xiaopeng
 * @version 1.0
 */
@Slf4j
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    //Spring Framework 提供的一个路径匹配工具类，用于处理路径模式的匹配操作。
    //它支持通配符匹配、路径变量解析等功能，常用于 Web 应用程序中处理 URL 路径的匹配规则。
    private final AntPathMatcher pathMatcher = new AntPathMatcher();

    // 定义需要跳过的路径
    private static final String[] EXCLUDE_PATHS = {
            "/user/login", // 登录接口
            "/user/register", // 注册接口

            "/captcha/**" , // 验证码接口

            "/swagger-ui/**", // Swagger
            "/v3/api-docs/**",
            "/webjars/**",
            "/swagger-resources/**",
            "/doc.html",
            "/favicon.ico",
            "/wxCheck",
            "/wx/**",

            "/.well-known/**"
    };

    /**
     * 判断当前请求是否需要过滤
     *
     * @param request
     * @return
     */
    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) {
        String path = request.getRequestURI(); // 改为获取完整URI
        return Arrays.stream(EXCLUDE_PATHS)
                .anyMatch(pattern -> pathMatcher.match(pattern, path));
    }

    @Override
    protected void doFilterInternal(
            @NonNull HttpServletRequest request,
            @NonNull HttpServletResponse response,
            @NonNull FilterChain filterChain
    ) throws IOException {
        try {
            // 1. 从请求头获取 Token（如 Authorization: Bearer xxx）
            String path = request.getServletPath();
            String token = extractToken(request);

            log.debug("Processing request to: {}, Token present: {}", path, token != null);
            System.out.println("Authorization Header: " + request.getHeader("Authorization"));

            // 2. Token基础验证
            if (token == null) {
                sendErrorResponse(response,
                        HttpStatus.UNAUTHORIZED.value(), // 401 表示未授权
                        "Authorization token is required");
                return;
            }

            // 3. 验证 Token
            if (!JwtUtils.isJwtValid(token)) {
                sendErrorResponse(response,
                        HttpStatus.UNAUTHORIZED.value(),
                        "Invalid or expired token");
                return;
            }

            // 4. 解析 token
            Claims claims = JwtUtils.parseJWT(token);
            log.info("Token Claims:" + claims);
            if (claims == null) {
                sendErrorResponse(response,
                        HttpStatus.UNAUTHORIZED.value(),
                        "Malformed token content: Claims of Token is null!");
                return;
            }

            // 5. 验证权限
            String userNO = claims.get("user_no").toString();
            Integer isAdmin = claims.get("isAdmin", Integer.class);
            String role = (isAdmin != null && isAdmin == 1) ? "ROLE_ADMIN" : "ROLE_USER"; // 必须加 ROLE_ 前缀

            List<GrantedAuthority> authorities = new ArrayList<>();
            authorities.add(new SimpleGrantedAuthority(role));

            // 6. 构建 Authentication 对象，在 Controller 或方法上使用 @PreAuthorize("hasRole('ADMIN')") 时，
            // Spring Security 会从 SecurityContext 中获取 Authentication，检查用户权限。
            UsernamePasswordAuthenticationToken authentication =
                    new UsernamePasswordAuthenticationToken(userNO, null, authorities);

            log.info("Authenticated user: {}, role: {}", userNO, role);

            // 7. 存入 SecurityContext
            SecurityContextHolder.getContext().setAuthentication(authentication);
            log.info("当前用户权限: {}",
                    SecurityContextHolder.getContext().getAuthentication().getAuthorities());

            // 8. 放行请求
            filterChain.doFilter(request, response);
        } catch (Exception e) {
            log.error("Authentication processing failed", e);
            sendErrorResponse(response,
                    HttpStatus.INTERNAL_SERVER_ERROR.value(),
                    "Authentication service error");
        }
    }

    // 辅助方法：发送错误响应
    private void sendErrorResponse(HttpServletResponse response,
                                   int status,
                                   String message) throws IOException {
        response.setStatus(status);
        response.setContentType("application/json");
        response.getWriter().write(
                String.format("{\"code\": %d, \"message\": \"%s\"}", status, message));
    }

    // 辅助方法：从请求头中提取 Token
    private String extractToken(HttpServletRequest request) {
        String header = request.getHeader("Authorization");
        if (header != null && header.startsWith("Bearer ")) {
            return header.substring(7); // 去掉 "Bearer "
        }
        return null;
    }
}
